package com.zxyankh.common.rpc.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.pool.AbstractChannelPoolMap;
import io.netty.channel.pool.ChannelPoolMap;
import io.netty.channel.pool.FixedChannelPool;
import io.netty.channel.pool.SimpleChannelPool;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;

import java.net.InetSocketAddress;

/**
 * @author ankh
 * @since 04.11.2017
 */
public class NettyClient {

    private static final Bootstrap BOOTSTRAP = new Bootstrap();
    private static final EventLoopGroup EVENT_LOOP_GROUP;
    private static ChannelPoolMap<InetSocketAddress, SimpleChannelPool> channelPoolMap;

    static {
        int threadNumber = Runtime.getRuntime().availableProcessors() * 2;
        EVENT_LOOP_GROUP = new NioEventLoopGroup(threadNumber);
        BOOTSTRAP.group(EVENT_LOOP_GROUP).channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true);

        channelPoolMap = new AbstractChannelPoolMap<InetSocketAddress, SimpleChannelPool>() {
            @Override
            protected SimpleChannelPool newPool(InetSocketAddress key) {
                return new FixedChannelPool(BOOTSTRAP.remoteAddress(key), new ClientConnPool(), threadNumber);
            }
        };
    }

    public static void call(String host, int port, Object msg) {
        InetSocketAddress inetSocketAddress = new InetSocketAddress(host, port);
        final SimpleChannelPool pool = channelPoolMap.get(inetSocketAddress);
        Future<Channel> future = pool.acquire();
        future.addListener((FutureListener<Channel>) f -> {
            if (f.isSuccess()) {
                Channel ch = f.getNow();
                ch.writeAndFlush(msg);
                pool.release(ch);
            }
        });
    }

}
